#!/bin/bash

# Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
# at the Lawrence Livermore National Laboratory. All Rights reserved. See files
# LICENSE and NOTICE for details. LLNL-CODE-806117.
#
# This file is part of the MFEM library. For more information and source code
# availability visit https://mfem.org.
#
# MFEM is free software; you can redistribute it and/or modify it under the
# terms of the BSD-3 license. We welcome feedback and contributions, see file
# CONTRIBUTING.md for details.

# Set the test and run directories
run_dir=`pwd`
test_dir=$( cd "$( dirname "$0" )" && pwd )

# Print usage information
case $1 in
   -h|-help)
      cat <<EOF

   $0 [-h|-help] {mfem_dir} {test1} {test2} ...

   where: {mfem_dir}  is the MFEM source directory [default value: ../..]
          {test1}...  are the sequence of tests to run
          -h|-help    prints this usage information and exits

   This script runs a sequence of tests using the code in mfem_dir (note that
   specifying the directory is optional). For each test, the standard output and
   standard error are saved in files test.out and test.err respectively in the
   current directory [1]. The output file interleaves stdout and stderr, while
   the error file is filtered by removing test-specific patterns specified in an
   optional test.filters file in the test directory [2]. After filtering, empty
   error files are erased, signifying that the corresponding test has passed.

   [1] run directory  = $run_dir
   [2] test directory = $test_dir

   Example usage: $0 ../..

EOF
      exit
      ;;
esac

# Setup
if [ -d "$1" ]; then
   mfem_dir="$1"
   shift
fi
if [ "$mfem_dir" = "" ]; then
    mfem_dir="../.."
fi
if [ ! -d "$mfem_dir" ] || [ ! -f "$mfem_dir/mfem.hpp" ]; then
   # Very unlikely
   printf "\nInvalid mfem directory: $mfem_dir\n\n" 1>&2
   exit 1
fi

# Determine current machine based on $SYS_TYPE or hostname
if [ $SYS_TYPE ]; then
   host="$SYS_TYPE"
else
   host=`hostname -s`
fi

runtest_check=0

# Execute the given sequence of tests
for testcmd in "$@"
do
   # Run a test
   eval test_cmd=(${testcmd})
   test="${test_cmd[0]}"
   this_test=`basename $test`
   rm -f "$this_test.out" "$this_test.err" "$this_test.msg"
   if [ "$test" == "$this_test" ]; then
      this_dir="$test_dir"
   else
      this_dir=`dirname $test`
   fi
   test_cmd[0]="$this_test"
   if [ ! -x "$this_dir/$this_test" ]; then
      printf "Invalid test: '$this_test'\n"
      exit 1
   fi
   printf "\nRunning test '${test_cmd[*]}'... "
   { $this_dir/"$this_test" "$mfem_dir" "${test_cmd[@]:1}" 2>&1 1>&3 |
     tee "$this_test.err"; } > "$this_test.out" 3>&1

   # Apply filters to the *.err file
   if [ -s "$this_test.err" ] && [ -e "$this_dir/$this_test.filters" ]; then
      mv "$this_test.err" "$this_test.tmp"
      egrep -v -f "$this_dir/$this_test.filters" "$this_test.tmp" \
         > "$this_test.err"
      # Remove lines with only white space.
      sed -e 's/^[[:space:]]*$//' "$this_test.err" > "$this_test.tmp"
      mv -f "$this_test.tmp" "$this_test.err"
   fi

   # Print the *.err file if not empty
   if [ -s "$this_test.err" ]; then
      runtest_check=1
      printf '\033[31m'"FAILED\n"'\033[0m'
      (printf '\033[31m'; cat "$this_test.msg"; printf '\033[0m') 1>&2
      echo "=== BEGIN error log from $this_test.err"
      (cat $this_test.err) 1>&2
      echo "=== END error log from $this_test.err"
   else
      printf '\033[32m'"OK\n"'\033[0m'
   fi

   # Remove the files generated by running the test
   rm -f $this_test.err $this_test.out "$this_test.msg"
done

printf "\n"

exit ${runtest_check}
